﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Collections;

namespace devtm.Verbatim.CustomConverters
{


    public class Converters
    {


        internal Hashtable container = new Hashtable();

        #region Converters

        public TTarget Convert<TSource, TTarget>(TSource source)
        {

            Func<TSource, object, CultureInfo, TTarget> c = null;
            if (GetConverter<TSource, TTarget>(out c))
            {
                return c(source, null, System.Globalization.CultureInfo.CurrentCulture);
            }

            return default(TTarget);

        }

        public TTarget Convert<TSource, TTarget>(TSource source, object parameters)
        {

            Func<TSource, object, CultureInfo, TTarget> c = null;
            if (GetConverter<TSource, TTarget>(out c))
            {
                return c(source, parameters, System.Globalization.CultureInfo.CurrentCulture);
            }

            return default(TTarget);

        }


        public TTarget Convert<TSource, TTarget>(TSource source, object parameters, CultureInfo culture)
        {

            Func<TSource, object, CultureInfo, TTarget> c = null;
            if (GetConverter<TSource, TTarget>(out c))
            {
                return c(source, parameters, culture);
            }

            return default(TTarget);

        }

        #endregion


        private bool GetConverter<TSource, TTarget>(out Func<TSource, object, CultureInfo, TTarget> converter)
        {

            Type t = typeof(IConverter<TSource, TTarget>);
            if (container.ContainsKey(t))
            {
                converter = container[t] as Func<TSource, object, CultureInfo, TTarget>;
                return true;
            }
            else
            {
                converter = null;
                return false;
            }

        }


        /// <summary>
        /// Initializes a new instance of the <see cref="Converter&lt;TSource, TTarget&gt;"/> class.
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <typeparam name="TTarget">The type of the target.</typeparam>
        /// <param name="converter">The converter.</param>
        public void Register<TSource, TTarget>(IConverter<TSource, TTarget> converter)
        {

            Type FingerPrint = typeof(IConverter<TSource, TTarget>);
            Type FingerPrintBack = typeof(IConverter<TTarget, TSource>);

            if (!container.ContainsKey(FingerPrint))
                lock (container)
                    if (!container.ContainsKey(FingerPrint))
                    {

                        Func<TSource, object, CultureInfo, TTarget> ConvertFunc = (source, parameter, culture) => converter.Convert(source, parameter, culture);
                        container.Add(FingerPrint, ConvertFunc);

                        if (!container.ContainsKey(FingerPrintBack))
                        {
                            Func<TTarget, object, CultureInfo, TSource> ConvertFuncBack = (source, parameter, culture) => converter.Convert(source, parameter, culture);
                            container.Add(FingerPrintBack, ConvertFuncBack);
                        }

                    }

        }

    }


}
